package jmine.tec.persist.schema.impl.elements.type;

import java.util.List;
import java.util.Set;

import jmine.tec.persist.schema.impl.elements.ColumnTypeElement;

import org.hibernate.type.Type;

/**
 * Interface para estratégias de tratamento de tipos, baseados na classe retornada pela propriedade.
 * 
 * @author lundberg
 */
public interface TypeStrategy {

    /**
     * Verifica se a estratégia é aplicável à propriedade, baseado na classe retornada pela propriedade.
     * 
     * @param columnTypeElement type element
     * @param type hibernate type
     * @return boolean
     */
    boolean matches(ColumnTypeElement columnTypeElement, Type type);

    /**
     * Obtém o sql type correto para o tipo mapeado, podendo ou não sobrescrever o tipo atual.
     * 
     * @param type type definido pelo hibernate
     * @param current código atual do tipo sendo utilizado
     * @return tipo que deveria ser colocado no lugar
     * @see java.sql.Types
     */
    int correctSqlType(Type type, int current);

    /**
     * Infere os parâmetros do tipo (length, precision, scale) necessários para o tipo mapeado,<br/>
     * podendo diminuir o tamanho do campo para o mínimo necessário
     * 
     * @param columnType elemento de tipo da coluna que deve ser ajustado
     * @param returnedClass classe mapeada
     */
    void inferTypeParameters(ColumnTypeElement columnType, Class<?> returnedClass);

    /**
     * Verifica se essa estratégia é capaz de enumerar um conjunto de valores permitidos para o campo, para geração de check constraint.
     * 
     * @return boolean
     */
    boolean hasLimitedAllowedValues();

    /**
     * Obtém o conjunto de elementos permitidos na coluna
     * 
     * @param returnedClass returnedClass
     * @return conjunto de elementos permitidos
     */
    Set<AllowedValue> getAllowedValues(Class<?> returnedClass);

    /**
     * Verifica se os parâmetros do tipo (length, precision, scale) definidos pelo usuário são suficientes e compatíveis com o tipo mapeado.
     * 
     * @param columnType elemento de tipo
     * @param returnedClass returnedClass
     * @return lista de mensagens que deve ser registradas como alertas
     */
    List<String> checkUserDefinedValues(ColumnTypeElement columnType, Class<?> returnedClass);
}
